﻿using Serilog;
using Summer.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Proto;
using GameServer.Database;
using GameServer.Mgr;
using GameServer.Network;
using Google.Protobuf;
using System.Numerics;
using GameServer.InventorySystem;
using static FreeSql.Internal.GlobalFilter;
using System.Runtime.ConstrainedExecution;
using System.Collections;
using System.Reflection.PortableExecutable;

namespace GameServer.Model
{
    //场景
    public class Space
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public SpaceDefine Def { get; set; }

        public int allMonsterInThisSpace = 1001;
        private int allItemInThisSpace = 0;
        public Connection thisSpaceBroker;

        //当前场景中全部的角色
        public Dictionary<int, Character> CharacterDict = new Dictionary<int, Character>();
        private Dictionary<int, NCharacter> NCharacterDict = new Dictionary<int, NCharacter>();

        public Dictionary<int, NMonster> NMonsterDict = new Dictionary<int, NMonster>();
        public Dictionary<int, Monster> MonsterDict = new Dictionary<int, Monster>();

        public Dictionary<int, ItemEntity> ItemDict = new Dictionary<int, ItemEntity>();
        public Dictionary<int, SpaceItemInfo> SpaceItemDict = new Dictionary<int, SpaceItemInfo>();

        private Dictionary<Connection, Character> ConnCharacter = new Dictionary<Connection, Character>();
        public MonsterManager monsterManager=new MonsterManager();
        public SpawnManager spawnManager = new SpawnManager();

        public Space(SpaceDefine def) { this.Def = def;
            this.Id = def.SID;
            this.Name = def.Name;
            monsterManager.Init(this);
            spawnManager.Init(this);
        }

        //角色进入场景
        public void CharacterJoin(Connection conn,Character character,NCharacter nCharacter)
        {
            Log.Information("角色进入场景:" + character.entityId);
            //conn.Set<Character>(character); //把角色存入连接
            //conn.Set<Space>(this);          //把场景存入连接
            conn.Get<Session>().Character = character;
            character.Space = this;

            CharacterDict[character.entityId] = character;
            NCharacterDict[character.entityId] = nCharacter;
            character.conn = conn;   
            if (!ConnCharacter.ContainsKey(conn))
            {
                ConnCharacter[conn] = character;
            }
            //把新进入的角色广播给其他玩家
            var resp = new SpaceCharactersEnterResponse();
            resp.SpaceId = this.Id; //场景ID
            resp.EntityList.Add(character.GetData());
            resp.NCharacterList.Add(nCharacter);
            foreach(var kv in CharacterDict)
            {
                if (kv.Value.conn != conn)
                {
                    kv.Value.conn.Send(resp);
                }
            }
            foreach (var kv in CharacterDict)
            {
                Log.Information("当前的地图编号是="+this.Id+"当前的玩家id是="+kv.Key+"当前的玩家是="+kv.Value.Name+"当前的地图里面玩家有="+ CharacterDict.Count);
            }
            //新上线的角色需要获取全部角色
            foreach (var kv in CharacterDict)
            {
                if (kv.Value.conn == conn) continue;
                resp.EntityList.Clear();
                resp.EntityList.Add(kv.Value.GetData());
                resp.NCharacterList.Clear();
                resp.NCharacterList.Add(NCharacterDict[kv.Key]);
                conn.Send(resp);
            }

            //上线的玩家获取之前场景里面就有的怪物
            var monster_resp = new SpaceMonsterEnterResponse();
            foreach (var kv in MonsterDict)
            {
                if (kv.Value.IsDead == false)
                {
                    Log.Debug("在这里发送了怪物的数据，怪物的id是{0},怪物的类型是{1},怪物的位置是{2}", kv.Value.entity_id, kv.Value.type_id, kv.Value.Position);
                    monster_resp.EntityList.Clear();
                    monster_resp.EntityList.Add(kv.Value.GetData());
                    monster_resp.NNMonsterList.Clear();
                    monster_resp.NNMonsterList.Add(NMonsterDict[kv.Key]);
                    conn.Send(monster_resp);
                }
            }

            //上线的玩家获取之前场景里面就有的掉落物
            SpaceItemEnterResponse itemEnterResponse = new SpaceItemEnterResponse();
            foreach (var kv in SpaceItemDict)
            {
                itemEnterResponse.SpaceItemList.Clear();
                itemEnterResponse.SpaceItemList.Add(kv.Value);
                conn.Send(itemEnterResponse);
            }
        }

        /// <summary>
        /// 角色离开地图
        /// 客户端离线、切换地图
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="character"></param>
        public void CharacterLeave(Connection conn,Character character)
        {
            Log.Information("角色离开场景:" + character.entityId);
            conn.Set<Space>(null);          //取消conn的场景记录
            CharacterDict.Remove(character.entityId);
            ConnCharacter.Remove(character.conn);
            NCharacterDict.Remove(character.entityId);
            SpaceCharacterLeaveResponse resp = new SpaceCharacterLeaveResponse();
            resp.EntityId = character.entityId;
            foreach (var kv in CharacterDict)
            {
                kv.Value.conn.Send(resp);
            }
        }

        /// <summary>
        /// 广播更新Entity信息
        /// </summary>
        /// <param name="entitySync"></param>
        public void UpdateEntity(NEntitySync entitySync)
        {
            if(entitySync.Entity.Id>=1000)
            {
                MonsterDict[entitySync.Entity.Id].SetEntityData(entitySync.Entity,entitySync.State);
            }
            foreach (var kv in CharacterDict)
            {
                if(kv.Value.entityId == entitySync.Entity.Id)
                {
                    kv.Value.SetEntityData(entitySync.Entity,entitySync.State);
                    var chr = kv.Value;
                    chr.Data.X= entitySync.Entity.Position.X;
                    chr.Data.Y = entitySync.Entity.Position.Y;
                    chr.Data.Z = entitySync.Entity.Position.Z;
                }
                else
                {
                    SpaceEntitySyncResponse resp = new SpaceEntitySyncResponse();
                    resp.EntitySync = entitySync;
                    kv.Value.conn.Send(resp);
                }
            }
        }
        /// <summary>
        /// 刷新数据库里面的怪物和玩家的数据
        /// </summary>
        /// <param name="entitySync"></param>
        public void UpdateEntityRoleInfo(GameEntityRoleInfoMessage  gameEntityRoleInfo)
        {
            if (gameEntityRoleInfo.EntityId >= 1000)
            {
                MonsterDict[gameEntityRoleInfo.EntityId].SetMonsterRoleInfo(gameEntityRoleInfo);
            }
            foreach (var kv in CharacterDict)
            {
                if (kv.Value.entityId == gameEntityRoleInfo.EntityId)
                {
                    kv.Value.SetCharacterRoleInfo(gameEntityRoleInfo);
                }
                SpaceEntityRoleInfoSyncResponse resp = new SpaceEntityRoleInfoSyncResponse();
                resp.CharacterRoleInfo = gameEntityRoleInfo;
                kv.Value.conn.Send(resp);
            }
        }
        public void MonsterEnter(Monster mon)
        {
            allMonsterInThisSpace++;
            //把新进入的角色广播给其他玩家
            var resp = new SpaceMonsterEnterResponse();
            mon.Space = this;
            resp.SpaceId = this.Id; //场景ID
            resp.EntityList.Add(mon.GetData());
            NMonster nMonster = new NMonster()
            {
                TypeId = mon.type_id,
                Name = mon.name,
                EntityId = mon.entity_id,
                Level = mon.level,
                SpaceId = this.Id,
                Gold = mon.gold,
                Hp = mon.hp,
                Mp = mon.mp,
                Attack = mon.attack,
                Defense = mon.defense,
                Magic = mon.magic,
                Magicdefense = mon.magicdefense,
                Speed = mon.speed,
                MonsterInitPos = mon.initPosition,
                Baoji = mon.baoji,
                Baojidefense = mon.baojidefense,
            };
            NMonsterDict[mon.entityId] = nMonster;
            MonsterDict[mon.entityId] = mon;
            resp.NNMonsterList.Add(nMonster);
            foreach (var kv in CharacterDict)
            {
                kv.Value.conn.Send(resp);
            }
        }
        public void UpdateSkillInSpace(SyncSkillRequest skillRequestEntityID)
        {
            foreach (var kv in CharacterDict)
            {
                if (kv.Value.entityId != skillRequestEntityID.EntityId)
                {
                    SyncSkillResponse resp = new SyncSkillResponse();
                    resp.SkillID = skillRequestEntityID.SkillID;
                    resp.Skillposition = skillRequestEntityID.Skillposition;
                    kv.Value.conn.Send(resp);
                }
            }
        }
        /// <summary>
        /// 广播Proto消息给场景的全体玩家
        /// </summary>
        /// <param name="msg"></param>
        public void Broadcast(IMessage msg)
        {
            foreach (var kv in CharacterDict)
            {
                kv.Value.conn.Send(msg);
            }
        }
        public void Update()
        {
            this.spawnManager.Update();
        }

        public void ChuanJianWuPing(int itemID, Vector3Int pos, Vector3Int dir)
        {
            if (DataManager.Instance.InventoryItemDict.ContainsKey(itemID))
            {
                allItemInThisSpace++;
                ItemEntity item=new ItemEntity()
                {
                    ID = itemID,
                    Pos=pos,
                    Dir=dir,
                    itemID=allItemInThisSpace,
                    name= DataManager.Instance.InventoryItemDict[itemID].name,
                    ItemType= DataManager.Instance.InventoryItemDict[itemID].ItemType,
                    Quality= DataManager.Instance.InventoryItemDict[itemID].Quality,
                    Description= DataManager.Instance.InventoryItemDict[itemID].Description,
                    Capicity= DataManager.Instance.InventoryItemDict[itemID].Capicity,
                    BuyPrice= DataManager.Instance.InventoryItemDict[itemID].BuyPrice,
                    SellPrice= DataManager.Instance.InventoryItemDict[itemID].SellPrice,
                    Icon= DataManager.Instance.InventoryItemDict[itemID].Icon,
                    Model= DataManager.Instance.InventoryItemDict[itemID].Model,
                    Speed= DataManager.Instance.InventoryItemDict[itemID].Speed,
                    HPMAX= DataManager.Instance.InventoryItemDict[itemID].HPMAX,
                    MPMAX= DataManager.Instance.InventoryItemDict[itemID].MPMAX,
                    AD= DataManager.Instance.InventoryItemDict[itemID].AD,
                    AP= DataManager.Instance.InventoryItemDict[itemID].AP,
                    DEF= DataManager.Instance.InventoryItemDict[itemID].DEF,
                    MagicDef= DataManager.Instance.InventoryItemDict[itemID].MagicDef,
                    CRI= DataManager.Instance.InventoryItemDict[itemID].CRI,
                    CRD= DataManager.Instance.InventoryItemDict[itemID].CRD,
                    HitRate= DataManager.Instance.InventoryItemDict[itemID].HitRate,
                    HPRegon= DataManager.Instance.InventoryItemDict[itemID].HPRegon,
                    MPRegon= DataManager.Instance.InventoryItemDict[itemID].MPRego,
                    space=this
                };
                ItemDict[allItemInThisSpace] = item;
            }
            SpaceItemEnterResponse itemEnterResponse = new SpaceItemEnterResponse();
            itemEnterResponse.SpaceId = this.Id;
            SpaceItemInfo itemInfo = new SpaceItemInfo();
            itemInfo.ItemId = itemID;
            itemInfo.Position = pos;
            itemInfo.DictId = allItemInThisSpace;
            SpaceItemDict[allItemInThisSpace]=(itemInfo);
            itemEnterResponse.SpaceItemList.Add(itemInfo);
            foreach (var kv in CharacterDict)
            {
                kv.Value.conn.Send(itemEnterResponse);
            }
        }

        /// <summary>
        /// 演员离开场景
        /// </summary>
        /// <param name="actor"></param>
        public void EntityLeave(Character actor)
        {
            Log.Information("角色离开场景:" + actor.entityId);
            CharacterDict.Remove(actor.entityId);
            ConnCharacter.Remove(actor.conn);
            NCharacterDict.Remove(actor.entityId);
            SpaceCharacterLeaveResponse resp = new SpaceCharacterLeaveResponse();
            resp.EntityId = actor.entityId;
            Broadcast(resp);
        }

        /// <summary>
        /// 场景物品离开场景
        /// </summary>
        /// <param name="actor"></param>
        public void ItemLeave(ItemEntity itemEnt)
        {
            foreach (var item in ItemDict.Keys)
            {
                if (ItemDict[item] == itemEnt)
                {
                    ItemDict.Remove(item);
                    SpaceItemDict.Remove(item);
                    SpaceItemResonse resp = new SpaceItemResonse();
                    resp.ItemID = item;
                    Broadcast(resp);
                }
            }
        }

        public void EntityEnter(Connection conn, Character character, NCharacter nCharacter)
        {
            Log.Information("角色进入场景:" + character.entityId);
            character.Space = this;

            CharacterDict[character.entityId] = character;
            NCharacterDict[character.entityId] = nCharacter;
            //把新进入的角色广播给其他玩家
            var resp = new SpaceCharactersEnterResponse();
            resp.SpaceId = this.Id; //场景ID
            resp.EntityList.Add(character.GetData());
            resp.NCharacterList.Add(nCharacter);
            foreach (var kv in CharacterDict)
            {
                if (kv.Value.conn != conn)
                {
                    kv.Value.conn.Send(resp);
                }
            }
            foreach (var kv in CharacterDict)
            {
                Log.Information("当前的地图编号是=" + this.Id + "当前的玩家id是=" + kv.Key + "当前的玩家是=" + kv.Value.Name + "当前的地图里面玩家有=" + CharacterDict.Count);
            }
            //新上线的角色需要获取全部角色
            foreach (var kv in CharacterDict)
            {
                if (kv.Value.conn == conn) continue;
                resp.EntityList.Clear();
                resp.EntityList.Add(kv.Value.GetData());
                resp.NCharacterList.Clear();
                resp.NCharacterList.Add(NCharacterDict[kv.Key]);
                conn.Send(resp);
            }

            //上线的玩家获取之前场景里面就有的怪物
            var monster_resp = new SpaceMonsterEnterResponse();
            foreach (var kv in MonsterDict)
            {
                if (kv.Value.IsDead == false)
                {
                    Log.Debug("在这里发送了怪物的数据，怪物的id是{0},怪物的类型是{1},怪物的位置是{2}", kv.Value.entity_id, kv.Value.type_id, kv.Value.Position);
                    monster_resp.EntityList.Clear();
                    monster_resp.EntityList.Add(kv.Value.GetData());
                    monster_resp.NNMonsterList.Clear();
                    monster_resp.NNMonsterList.Add(NMonsterDict[kv.Key]);
                    conn.Send(monster_resp);
                }
            }
        }

        public void Telport(Actor actor, Vector3Int pos, Vector3Int dir = new())
        {
            actor.Position = pos;
            actor.Direction = dir;
            SpaceEntitySyncResponse resp = new SpaceEntitySyncResponse();
            resp.EntitySync = new NEntitySync();
            resp.EntitySync.Entity= new NEntity();
            resp.EntitySync.Entity.Id = actor.entityId;
            resp.EntitySync.Entity.Position = pos;
            resp.EntitySync.Entity.Direction = dir;
            resp.EntitySync.Force = true;
            Broadcast(resp);
        }
    }
}
